<template>
  <view class="c-input-box" :style="[...inpitStyle]">
    <view
      class="label"
      :style="[...labelStyle]"
      :class="{ required: rules.isVerify }"
    >
      {{ label }}
    </view>
    <view class="boxs">
      <view
        class="c-input"
        :class="ggclass"
        :style="{
          width,
          height: heights,
          padding,
          borderRadius: radiuss,
          borderColor: borderShow ? focusBorderColors : borderColors,
          borderStyle: borderStyles,
          borderLeft: isBorders ? '' : 'transparent',
          borderRight: isBorders ? '' : 'transparent',
          borderTop: isBorders ? '' : 'transparent',
          background: computedBgColor,
        }"
      >
        <view
          class="defaultView"
          v-if="$slots.default"
          :style="{ 'justify-content': slotJcs }"
        >
          <slot> </slot>
        </view>
        <view class="input-box" v-else>
          <view class="before" v-if="$slots.before">
            <slot name="before"></slot>
          </view>
          <input
            :focus="isfocus"
            class="input"
            v-if="type === 'text'"
            placeholder-class="placeholder"
            type="text"
            v-model="val"
            :placeholder="hint"
            :maxlength="maxlength"
            @focus="focus"
            @blur="blur"
            @input="oninput"
            @change="onchange"
            :style="{ textAlign: textAligns }"
            :disabled="disabled"
            :confirm-type="confirmType"
            @confirm="confirm"
            :adjust-position="adjustPosition"
            @keyboardheightchange="keyboardheightchange"
          />
          <view class="password-box" v-if="type === 'password'">
            <input
              :focus="isfocus"
              class="input"
              placeholder-class="placeholder"
              :type="isShow ? 'text' : 'password'"
              v-model="val"
              :placeholder="hint"
              :maxlength="maxlength"
              @focus="focus"
              @blur="blur"
              @input="oninput"
              @change="onchange"
              :style="{ textAlign: textAligns }"
              :disabled="disabled"
              :confirm-type="confirmType"
              @confirm="confirm"
              :adjust-position="adjustPosition"
              @keyboardheightchange="keyboardheightchange"
            />
            <text
              v-if="eye"
              class="iconfont"
              :class="isShow ? 'icon-zhengyan' : 'icon-biyan'"
              @click="eyechange"
            ></text>
          </view>

          <input
            :focus="isfocus"
            class="input"
            v-if="type === 'number'"
            placeholder-class="placeholder"
            type="number"
            v-model.number="val"
            :placeholder="hint"
            :maxlength="maxlength"
            @focus="focus"
            @blur="blur"
            @input="oninput"
            @change="onchange"
            :style="{ textAlign: textAligns }"
            :disabled="disabled"
            :confirm-type="confirmType"
            @confirm="confirm"
            :adjust-position="adjustPosition"
            @keyboardheightchange="keyboardheightchange"
          />

          <input
            :focus="isfocus"
            class="input"
            v-if="type === 'nickname'"
            placeholder-class="placeholder"
            type="nickname"
            v-model.number="val"
            :placeholder="hint"
            :maxlength="maxlength"
            @focus="focus"
            @blur="blur"
            @input="oninput"
            @change="onchange"
            :style="{ textAlign: textAligns }"
            :disabled="disabled"
            :confirm-type="confirmType"
            @confirm="confirm"
            :adjust-position="adjustPosition"
            @keyboardheightchange="keyboardheightchange"
          />

          <textarea
            :focus="isfocus"
            v-if="type === 'textarea'"
            class="input textarea"
            placeholder-class="placeholder"
            :placeholder="hint"
            v-model="val"
            :maxlength="maxlength"
            @focus="focus"
            @blur="blur"
            @input="oninput"
            @change="onchange"
            :style="{ textAlign: textAligns }"
            :disabled="disabled"
            :confirm-type="confirmType"
            @confirm="confirm"
            :adjust-position="adjustPosition"
            @keyboardheightchange="keyboardheightchange"
          />
        </view>
        <view class="after" v-if="$slots.after">
          <slot name="after"></slot>
        </view>
      </view>
      <view class="error" v-if="isError">{{ rules.hint || "请输入" }}</view>
    </view>
  </view>
</template>

<script setup lang="ts">
import propsMixin from "../mixins/props/index";
import {
  ref,
  computed,
  onMounted,
  toRefs,
  reactive,
  defineProps,
  inject,
  provide,
  watch,
  getCurrentInstance,
} from "vue";
const { proxy } = getCurrentInstance() as any;
const cForm: any = inject("cForm");
const elFormItem = inject("elFormItem");

const props = defineProps({
  ...propsMixin.props,
  confirmType: {
    //键盘下面的按钮类型 send-“发送” search-“搜索” next-“下一个”	 go	-“前往”	done-“完成”
    type: String,
    default: "done",
  },
  type: {
    //输入框类型
    type: String,
    default: "text",
  },
  textAlign: {
    //文字排列方式
    type: String,
    default: "",
  },
  hint: {
    //占位文字
    type: String,
    default: "请输入",
  },
  maxlength: {
    //最大输入文字数量 -1 为不限制
    type: Number,
    default: -1,
  },
  modelValue: {
    //输入框值
    type: [String, Number, Boolean, Object],
    default: "",
  },
  eye: {
    //看密码的眼睛
    type: Boolean,
    default: false,
  },
  width: {
    //宽度
    type: String,
    default: "",
  },
  height: {
    //高度
    type: String,
    default: "",
  },
  padding: {
    //内边距
    type: String,
    default: "",
  },
  radius: {
    //圆角
    type: String,
    default: "",
  },
  borderColor: {
    //边框颜色
    type: String,
    default: "",
  },
  focusBorderColor: {
    //聚焦边框颜色
    type: String,
    default: "",
  },
  isBorder: {
    //是否带边框
    type: [String, Boolean],
    default: "",
  },
  borderStyle: {
    //边框样式
    type: String,
    default: "",
  },
  disabled: {
    //是否禁用
    type: Boolean,
    default: false,
  },
  adjustPosition: {
    //键盘弹起时，是否自动上推页面
    type: Boolean,
    default: true,
  },
  label: {
    type: String,
    default: "",
  },
  labelPosition: {
    type: String,
    default: "",
  },
  labelWidth: {
    type: String,
    default: "",
  },
  rule: {
    //验证对象 {isVerify:true,hint:'请输入'，fun:()=>{}}
    type: [Object, String],
    default: () => {
      return {};
    },
  },
  isfocus: {
    //是否聚焦
    type: Boolean,
    default: false,
  },
  slotJc: {
    //插槽排列方式
    type: String,
    default: "",
  },
});

const state = reactive<any>({
  isShow: false,
  borderShow: false,
  isError: false,
  isopenP: false,
  rules: {},
});
const { isShow, borderShow, isError, isopenP, rules } = toRefs(state);
watch(
  () => props.rule,
  (n) => {
    if (!n) return;
    state.rules = n;
    if (typeof n === "string") {
      n = JSON.parse(n);
    }
    if (cForm.pushInputVerify && state.rules.isVerify) {
      cForm.pushInputVerify(verify);
    }
  },
  { deep: true, immediate: true }
);
onMounted(() => {
  // if(this.isfocus){}
  state.isopenP = cForm?.isOpenPattern || props.isOpenPattern;
});

const val = computed({
  get() {
    return state.modelValue;
  },
  set(val) {
    proxy.$emit("input", val);
  },
});
const borderColors = computed(() => {
  return props.borderColor || proxy.$inputStyle.borderColor;
});
const focusBorderColors = computed(() => {
  if (state.isError) {
    setTimeout(() => {
      state.borderShow = true;
    }, 200);
    return "red";
  }
  let a = proxy.$inputStyle.focusBorderColor || proxy.$color.main;
  return props.focusBorderColor || a;
});
const isBorders = computed(() => {
  let a =
    props.isBorder === "" ? (proxy.$inputStyle || {}).isBorder : props.isBorder;
  return props.isBorder || a;
});
const radiuss = computed(() => {
  if (!isBorders.value) return "0rpx";
  return props.radius || (proxy.$inputStyle || {}).radius;
});
const borderStyles = computed(() => {
  return props.borderStyle || (proxy.$inputStyle || {}).borderStyle;
});
const computedBgColor = computed(() => {
  return props.background || (proxy.$inputStyle || {}).background;
});
const heights = computed(() => {
  return props.height || (proxy.$inputStyle || {}).height;
});
const poss = computed(() => {
  return props.labelPosition || (cForm || {}).labelPosition;
});
const labelStyle = computed(() => {
  let m = "10rpx";
  let params: any = {};
  if (poss.value === "top") {
    params.marginBottom = m;
  } else {
    params.marginRight = m;
  }
  params.width = props.labelWidth || cForm.labelWidth;
  params.color = computedColor.value;
  return params;
});
const inpitStyle = computed(() => {
  let params: any = {};
  params.width = "100%";
  params.display = "flex";
  if (poss.value === "top") {
    params.flexDirection = "column";
  } else {
    params.alignItems = "center";
    params.flexDirection = "row";
  }
  return params;
});
const slotJcs = computed(() => {
  return props.slotJc || (cForm || {}).slotJc;
});
const textAligns = computed(() => {
  return props.textAlign || (cForm || {}).textAlign;
});
const computedColor = computed(() => {
  if (props.isOpenPattern) {
    return proxy.$color.theme.textColor;
  }
  // return this.color || this.$color.theme.textColor
  return props.color || "#333";
});

const keyboardheightchange = (e: any) => {
  if (!props.adjustPosition) {
    proxy.$bus.$emit("keyHeight", e.target.height);
  }
};
const eyechange = () => {
  state.isShow = !state.isShow;
};
const focus = (e: any) => {
  // this.isfocus = true
  state.borderShow = true;
  proxy.$emit("focus", e.target.value);
};
const blur = (e: any) => {
  // this.isfocus = false
  state.borderShow = false;
  proxy.$emit("blur", e.target.value);
  verify();
};
const oninput = (e: any) => {
  proxy.$emit("update:modelValue", e.target.value);
};
const onchange = (e: any) => {
  val.value = e.target.value;
  proxy.$emit("change", e.target.value);
};
const confirm = (e: any) => {
  proxy.$emit("confirm", e.target.value);
};
const verify = () => {
  if (state.rules.isVerify) {
    if (state.rules.fun) {
      state.rules.fun(val.value, (res: any) => {
        if (typeof res === "boolean") {
          state.isError = !res;
        } else {
          state.isError = !!res;
          state.rules.hint = res;
        }
      });
    } else if (state.rules.mode === "pattern") {
      let re = new RegExp(state.rules.pattern);
      if (re.test(val.value)) {
        state.isError = false;
      } else {
        state.isError = true;
      }
    } else if (state.rules.mode === "len") {
      if ((val.value || "").length > state.rules.len) {
        state.isError = true;
      } else {
        state.isError = false;
      }
    } else if (state.rules.mode === "max") {
      if ((val.value || "").length > state.rules.max) {
        state.isError = true;
      } else {
        state.isError = false;
      }
    } else if (state.rules.mode === "min") {
      if ((val.value || "").length < state.rules.min) {
        state.isError = true;
      } else {
        state.isError = false;
      }
    } else {
      state.isError =
        val.value === "" || val.value === null || val.value === undefined;
    }
    return state.isError;
  }
  return true;
};

provide("Cinput", { ...props });
</script>

<style lang="scss" scoped>
.error {
  color: red;
  font-size: 24rpx;
}

.required::after {
  content: "*";
  color: red;
}

.c-input-box {
  .label{
    white-space:nowrap;
    font-size: 28rpx;
  }
}

.placeholder {
  font-size: 28rpx;
  color: grey;
}

.boxs {
  display: flex;
  flex-direction: column;
  // align-items: center;
  justify-content: center;
  width: 100%;
}

.c-input {
  // flex: 1;
  width: 100%;
  height: 70rpx;
  border: solid 2rpx #ccc;
  border-radius: 10rpx;
  padding: 0 20rpx 0 20rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;

  .defaultView {
    width: 100%;
    height: 100%;
    display: inline-flex;
    align-items: center;
  }

  .input-box {
    flex: 1;
    display: flex;
    align-items: center;
    height: 100%;

    .before {
      margin-right: 10rpx;
    }

    .input {
      flex: 1;
      font-size: 28rpx;
      height: 100%;
    }

    .textarea {
      box-sizing: border-box;
      padding: 20rpx 0;
    }
  }

  .after {
    margin-left: 10rpx;
  }
}

.password-box {
  flex: 1;
  display: flex;
  align-items: center;
  height: 100%;

  .iconfont {
    width: 80rpx;
    height: 50rpx;
    display: inline-flex;
    justify-content: flex-end;
    align-items: center;
  }
}
</style>